export {}
// 自定义高级类型
// 1.Proxy和unProxify
namespace Proxy {
    type Proxy<T> = {
        get(): T;
        set(value: T): void;
    }
    type Proxify<T> = {
        [P in keyof T]: Proxy<T[P]>
    }
    function proxify<T>(obj: T): Proxify<T> {
        // as 和 <>都具备强制转换  的效果
        let result = {} as Proxify<T>;
        for (const key in obj) {
            result[key] = {
                get: () => obj[key],
                set: (value) => obj[key] = value
            }
        }
        return result;
    }
    let props = {
        name: 'ikki',
        age: 10
    }
    let proxyProps = proxify(props);
    console.log(proxyProps);
    
    function unProxify<T>(t: Proxify<T>): T {
        let result = {} as T;
        for (const k in t) {
            result[k] = t[k].get();
        }
        return result;
    }
    
    let originProps = unProxify(proxyProps);
    console.log(originProps);
}

// 2.SetDifference  等于exclude  从 T 中排除出可分配给 U的元素.
namespace SetDifference {
    type SetDifference<T, U> = T extends U ? never : T;
}

// 3.Omit 忽略T中的K属性
namespace Omit {
    type SetDifference<T, U> = T extends U ? never : T;
    // keyof T = name|age|visible
    // SetDifference< keyof T,K> = name|visible
    type Omit<T , K extends keyof T> = Pick< T ,SetDifference< keyof T,K> >
    type Props = { name: string; age: number; visible: boolean };
    type OmitProps = Omit<Props, 'age'>;
}

// 4.Diff差异，从T中移除掉U里存在的属性
namespace Diff {
    type SetDifference<T, U> = T extends U ? never : T;
    type Diff <T extends object , U extends object> = Pick<T, SetDifference<keyof T, keyof U> >
    type Props = { name: string; age: number; visible: boolean };
    type DefaultProps = { age: number };
    type DiffProps = Diff<Props, DefaultProps>;
}

// 5.Intersection 交叉的属性 共同拥有的
namespace Intersection {
    type Intersection <T extends object , U extends object> = Pick<T, Extract<keyof T,keyof U>&Extract<keyof U,keyof T>>
    type Props = { name: string; age: number; visible: boolean };
    type DefaultProps = { age: number }; 
    type DuplicateProps = Intersection<Props, DefaultProps>; //{ age: number; }
}

// 6.Overwrite 是用U的属性覆盖T的相同属性.
namespace Overwrite {
    type SetDifference<T, U> = T extends U ? never : T;
    type Diff <T extends object , U extends object> = Pick<T, SetDifference<keyof T, keyof U> >
    type Intersection <T extends object , U extends object> = Pick<T, Extract<keyof T,keyof U>&Extract<keyof U,keyof T>>

    type Overwrite<T extends object , U extends object, I = Intersection<U,T>& Diff<T,U> > = Pick< I , keyof I>
    type Props = { name: string; age: number; visible: boolean };
    type NewProps = { age: string; other: string };
    type ReplacedProps = Overwrite<Props, NewProps>;  // Expect: { name: string; age: string; visible: boolean; }
}

// 7.Merge
// Merge<O1, O2>的作用是将两个对象的属性合并:
// Merge<O1, O2> = Compute + Omit<U, T>
namespace Merge {
    type O1 = {
        id: number;
        name: string;
    };
    type O2 = {
        id: number;
        age: number;
    };
    //Compute的作用是将交叉类型合并
    type Compute<A extends any> = A extends Function ? A : { [K in keyof A]: A[K] };
    type R1 = Compute<{ x: "x" } & { y: "y" }>;
    type Merge<O1 extends object, O2 extends object> = Compute<O1 & Omit<O2, keyof O1>>;
    type R2 = Merge<O1, O2>;
}
 
// 8.8 Mutable 将 T 的所有属性的 readonly 移除
type Mutable<T> = {
    -readonly [P in keyof T]: T[P]
}
